﻿using System;
using Csla.Xaml;
using Microsoft.Practices.Prism.Regions;
using BizControl.Presentation.Infrastructure.Controls;
using Microsoft.Practices.Prism;
using System.ComponentModel.Composition;
using BizControl.Library.BusinessObjects.Activities;
using BizControl.Presentation.Infrastructure.Constants;
using System.ComponentModel;
using BizControl.Presentation.ActivityEditModule.Views;
using Microsoft.Practices.Prism.Commands;
using BizControl.Presentation.Infrastructure.Helpers;
using System.Collections.Generic;
using BizControl.Library;
using BizControl.Library.BusinessObjects.Models;
using System.Windows;
using System.Windows.Input;
using BizControl.Library.BusinessObjects.BusinessRoles;
using BizControl.Library.BusinessObjects.Categories;
using BizControl.Library.BusinessObjects.Participants;
using BizControl.Library.BusinessObjects.Marks;
using BizControl.Library.BusinessObjects.People;

namespace BizControl.Presentation.ActivityEditModule.ViewModels
{
  [Export]
  [PartCreationPolicy(CreationPolicy.NonShared)]
  public class ActivityEditViewModel : ViewModel<ActivityBO>, INavigationAware, IConfirmNavigationRequest, IHeaderInfoProvider<string>
  {
    private IRegionManager _regionManager;

    private readonly DelegateCommand _closeCommand;
    private readonly DelegateCommand _addMarkCommand;
    private readonly DelegateCommand<ActivityMarkBO> _setMarkCompleteCommand;
    private readonly DelegateCommand<ActivityMarkBO> _editConditionsCommand;
    private readonly DelegateCommand _setCompleteCommand;

    [ImportingConstructor]
    public ActivityEditViewModel(IRegionManager regionManager)
    {
      _regionManager = regionManager;
      _closeCommand = new DelegateCommand(Close);
      _addMarkCommand = new DelegateCommand(AddMark);
      _setMarkCompleteCommand = new DelegateCommand<ActivityMarkBO>(SetMarkComplete, CanSetMarkComplete);
      _editConditionsCommand = new DelegateCommand<ActivityMarkBO>(EditConditions);
      _setCompleteCommand = new DelegateCommand(SetComplete, CanSetComplete);
    }

    private void Refresh()
    {
      DoRefresh(GetActivity);
    }

    private void RefreshAllProperties()
    {
      if (Model != null)
      {
        CommentsVM.Activity = Model;
        ParticipantsVM.Activity = Model;
        MarksConditionsVM.Activity = Model;
        DependentActivitiesVM.Activity = Model;
      }
      else
      {
        CommentsVM.Activity = null;
        ParticipantsVM.Activity = null;
        MarksConditionsVM.Activity = null;
        DependentActivitiesVM.Activity = null;
      }

      OnPropertyChanged("CommentsVM");
      OnPropertyChanged("ParticipantsVM");
      OnPropertyChanged("DependentActivitiesVM");
      OnPropertyChanged("MarksConditionsVM");
      OnPropertyChanged("SelectedCategory");
      OnPropertyChanged("Participants");
      OnPropertyChanged("PeopleParticipants");

      _setCompleteCommand.RaiseCanExecuteChanged();
      _setMarkCompleteCommand.RaiseCanExecuteChanged();
    }

    protected override void OnModelChanged(ActivityBO oldValue, ActivityBO newValue)
    {
      if (oldValue != null)
      {
        oldValue.PropertyChanged -= new PropertyChangedEventHandler(Model_PropertyChanged);
        newValue.Marks.ChildChanged -= new EventHandler<Csla.Core.ChildChangedEventArgs>(Marks_ChildChanged);
        newValue.Marks.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Marks_CollectionChanged);
        oldValue.Participants.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Participants_CollectionChanged);
        oldValue.Participants.ChildChanged -= new EventHandler<Csla.Core.ChildChangedEventArgs>(Participants_ChildChanged);
      }
      base.OnModelChanged(oldValue, newValue);
      if (newValue != null)
      {
        newValue.PropertyChanged += new PropertyChangedEventHandler(Model_PropertyChanged);
        newValue.Marks.ChildChanged += new EventHandler<Csla.Core.ChildChangedEventArgs>(Marks_ChildChanged);
        newValue.Marks.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Marks_CollectionChanged);
        newValue.Participants.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Participants_CollectionChanged);
        newValue.Participants.ChildChanged += new EventHandler<Csla.Core.ChildChangedEventArgs>(Participants_ChildChanged);
      }
      RefreshAllProperties();
    }

    void Marks_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
      _setMarkCompleteCommand.RaiseCanExecuteChanged();
    }

    void Marks_ChildChanged(object sender, Csla.Core.ChildChangedEventArgs e)
    {
      if (e.PropertyChangedArgs != null && e.PropertyChangedArgs.PropertyName == "CanSetComplete")
        _setMarkCompleteCommand.RaiseCanExecuteChanged();
    }

    void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      if (e.PropertyName == "CanSetComplete")
        _setCompleteCommand.RaiseCanExecuteChanged();
    }

    void Participants_ChildChanged(object sender, Csla.Core.ChildChangedEventArgs e)
    {
      OnPropertyChanged("Participants");
      OnPropertyChanged("PeopleParticipants");
    }

    void Participants_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
      OnPropertyChanged("Participants");
      OnPropertyChanged("PeopleParticipants");
    }

    ActivityBO GetActivity()
    {
      return _activity;
    }

    #region Handlers

    private void Close()
    {
      _regionManager.RequestNavigate(ShellRegionNames.MainContentRegion, ViewNames.ActivitiesViewName, NavigationCompleted);
    }

    private void AddMark()
    {
      if (Model != null)
        Model.Marks.AddMark();
    }

    private void EditConditions(ActivityMarkBO mark)
    {
      //if (MarksConditionsVM != null)
      //  MarksConditionsVM.SelectedMark = mark;
    }

    private void SetComplete()
    {
      if (Model != null)
        Model.SetComplete();
    }

    private bool CanSetComplete()
    {
      if (Model != null)
        return Model.CanSetComplete;
      return false;
    }

    private void SetMarkComplete(ActivityMarkBO mark)
    {
      if (mark != null)
        mark.SetComplete();
    }

    private bool CanSetMarkComplete(ActivityMarkBO mark)
    {
      if (mark != null)
        return mark.CanSetComplete;
      return false;
    }

    private void NavigationCompleted(NavigationResult result)
    {
    }

    #endregion

    #region Properties

    public ICommand CloseCommand
    {
      get { return _closeCommand; }
    }

    public ICommand AddMarkCommand
    {
      get { return _addMarkCommand; }
    }

    public ICommand SetMarkCompleteCommand
    {
      get { return _setMarkCompleteCommand; }
    }

    public ICommand EditConditionsCommand
    {
      get { return _editConditionsCommand; }
    }

    public ICommand SetCompleteCommand
    {
      get { return _setCompleteCommand; }
    }

    public Dictionary<string, int> Priorities
    {
      get
      {
        return BizControl.Presentation.Infrastructure.Helpers.Priorities.ObjectPrioritiesAsDictionary;
      }
    }

    private ActivityBO _activity;
    private ActivityBO Activity
    {
      get { return _activity; }
      set
      {
        if (_activity != value)
        {
          _activity = value;
          Refresh();
        }
      }
    }

    private CommentsViewModel _commentsVM;
    public CommentsViewModel CommentsVM
    {
      get
      {
        if (_commentsVM == null)
          if (Model != null)
            _commentsVM = new CommentsViewModel(Model);
        return _commentsVM;
      }
    }

    private ParticipantsViewModel _participantsVM;
    public ParticipantsViewModel ParticipantsVM
    {
      get
      {
        if (_participantsVM == null)
          if (Model != null)
            _participantsVM = new ParticipantsViewModel(Model);
        return _participantsVM;
      }
    }

    private DependentActivitiesViewModel _dependentActivitiesVM;
    public DependentActivitiesViewModel DependentActivitiesVM
    {
      get
      {
        if (_dependentActivitiesVM == null)
          if (Model != null)
            _dependentActivitiesVM = new DependentActivitiesViewModel(Model);
        return _dependentActivitiesVM;
      }
    }

    private MarksConditionsViewModel _marksConditionsVM;
    public MarksConditionsViewModel MarksConditionsVM
    {
      get
      {
        if (_marksConditionsVM == null)
          if (Model != null)
            _marksConditionsVM = new MarksConditionsViewModel(Model);
        return _marksConditionsVM;
      }
    }

    private CategoryList _categories;
    public CategoryList Categories
    {
      get
      {
        if (_categories == null)
          _categories = CategoryList.GetCategoryList(true);
        return _categories;
      }
    }

    public CategoryBO SelectedCategory
    {
      get
      {
        if (Model == null) return Categories[CategoryBO.GetEmptyCategory().CategoryId];
        return Categories[Model.CategoryId];
      }
      set
      {
        if (Model == null) return;
        Model.CategoryId = Categories[value.CategoryId].CategoryId;
        OnPropertyChanged("SelectedCategory");
      }
    }

    private ParticipantList _participants;
    public ParticipantList Participants
    {
      get
      {
        if (Model == null) return _participants;
        bool refresh = _participants == null || _participants.Count != Model.Participants.Count;
        if (!refresh)
        {
          foreach (var participant in Model.Participants)
          {
            if (_participants[participant.ParticipantId] == null)
            {
              refresh = true;
              break;
            }
            if (_participants[participant.ParticipantId].Person != participant.Person)
              _participants[participant.ParticipantId].UpdatePerson(participant.Person);
            if (_participants[participant.ParticipantId].Role != participant.Role)
              _participants[participant.ParticipantId].UpdateRole(participant.Role);
          }
        }
        if (refresh)
          _participants = ParticipantList.GetParticipantList(Model, true);
        return _participants;
      }
    }

    private PersonList _peopleParticipants = PersonList.NewPersonList();
    public PersonList PeopleParticipants
    {
      get
      {
        if (Model == null) return _peopleParticipants;
        _peopleParticipants.AllowChange();
        _peopleParticipants.Clear();
        foreach (var participant in Participants)
        {
          _peopleParticipants.Add(new PersonInfo(participant.Person));
        }
        _peopleParticipants.ForbidChange();
        return _peopleParticipants;
      }
    }

    #endregion

    #region INavigationAware Members

    public Guid Id { get; set; }
    public bool Initialized { get; set; }

    private void Initialize(Guid id)
    {
      Id = id;
      Initialized = true;
    }

    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
      string activityId = navigationContext.Parameters[NavigationParametersNames.IdName];
      if (!string.IsNullOrEmpty(activityId))
      {
        Guid id = Guid.Parse(activityId);
        if (Initialized && Id == id)
        {
          return true;
        }
        else if (!Initialized)
        {
          Initialize(id);
          return true;
        }
      }
      return false;
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
      string activityId = navigationContext.Parameters[NavigationParametersNames.IdName];
      string newActivity = navigationContext.Parameters[NavigationParametersNames.NewActivityName];
      string copyActivity = navigationContext.Parameters[NavigationParametersNames.CopyActivityName];
      if (!string.IsNullOrEmpty(activityId))
      {
        if (Model == null)
        {
          Guid id = Guid.Parse(activityId);
          Activity = ActivityBO.GetActivity(id);
          Initialize(id);
        }
      }
      else if (!string.IsNullOrEmpty(newActivity))
      {
        Activity = ActivityBO.NewActivity();
        Initialize(Activity.ActivityId);
      }
      else if (!string.IsNullOrEmpty(copyActivity))
      {
        string sourceActivityId = navigationContext.Parameters[NavigationParametersNames.SourceActivityIdName];
        if (!string.IsNullOrEmpty(sourceActivityId))
        {
          Guid sourceId = Guid.Parse(sourceActivityId);
          ActivityBO sourceActivity = ActivityBO.GetActivity(sourceId);
          Activity = ActivityBO.CopyActivity(sourceActivity);
          Initialize(Activity.ActivityId);
        }
      }
    }

    #endregion

    #region IConfirmNavigationRequest Members

    public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
    {
      ConfirmationHelper.ConfirmNavigationRequestSaveDlg<ActivityBO>(this, continuationCallback);
    }

    #endregion

    #region IHeaderInfoProvider<string> Members

    public string HeaderInfo
    {
      get { return BizControl.Presentation.ActivityEditModule.Properties.Resources.ActivityEditHeaderInfo; }
    }

    #endregion
  }
}
